// Cell names have been changed in this file by netl_namemap on Mon Jan  3 04:00:11 UTC 2022
////////////////////////////////////////////////////////////////////////////// 
//
//  gen_pcatch.v
//
//  Generic pulse catcher.  Will catch a pulse from one clock domain into
//  a second clock domain.  Can be configured to generate a one-cycle pulse
//  in the "catching" domain on either the rising or falling edge of the
//  caught pulse.
//
//  Original Author: Chris Jones
//  Current Owner:   Behram Minwalla
//
////////////////////////////////////////////////////////////////////////////// 
//
// Copyright (C) 2011 Synopsys, Inc.  All rights reserved.
//
// SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of
// Synopsys, Inc., and is fully protected under copyright and trade secret
// laws.  You may not view, use, disclose, copy, or distribute this file or
// any information contained herein except pursuant to a valid written
// license agreement. It may not be used, reproduced, or disclosed to others
// except in accordance with the terms and conditions of that agreement.
//
////////////////////////////////////////////////////////////////////////////// 
//
//    Perforce Information
//    $Author: ameer $
//    $File: //dwh/up16/main/dev/pma/dig/rtl/gen_pcatch.v $
//    $DateTime: 2014/05/02 08:59:04 $
//    $Revision: #3 $
//
////////////////////////////////////////////////////////////////////////////// 

module dwc_e12mp_phy_x4_ns_gen_pcatch
  #(parameter FALLING_EDGE = 0,
    parameter NO_EDGE = 0,
    parameter MAX_CHK_EN = 0, // Use setup window checking for metastability modelling.
    parameter SETUP = 900,
    parameter QRND = 1,
    parameter QVAL = 1,
    parameter META_FALL = 1) (
output wire q,
input  wire rst,
input  wire clk,
input  wire scan_mode_i,
input  wire scan_set_rst_i,
input  wire d
);


// MUX in the reset for ATPG
//
wire async_scan_rst;
dwc_e12mp_phy_x4_ns_gen_mux scan_rst_mux (
  .out (async_scan_rst),
  .sel (scan_mode_i),
  .d0  (d),
  .d1  (scan_set_rst_i)
);

// Add this func & scan mode reset register to reset 2 input stages.
// Since during scan mode, the rst pin will be connected to scan_rst, 
// ATPG can never test the synchronous rst logic on d_s2 reg, i.e. d_s1 & ~rst. 
// By using another register here, we keep the asynchronous reset behaviour, while 
// giving a scan flop to ATPG to use to test the synchronous path.
reg atpg_sync_rst;
always @(posedge clk or posedge rst) begin
  if (rst)
    atpg_sync_rst <= 1'b1;
  else
    atpg_sync_rst <= 1'b0;
end

`ifdef ANI_SIM_MODE
  // Create a shadow register that always samples new data on the clock (never goes metastable)
  reg shadow;
  always @ (posedge clk or posedge async_scan_rst)
        if (async_scan_rst)
      shadow <= 1'b1;
        else
      shadow <= 1'b0;

wire async_scan_rst_in_dly;
assign #(SETUP*0.001) async_scan_rst_in_dly = async_scan_rst;
`endif

// Capture the pulse using a typical reset synchronizer configuration.  We
// only use two flops since we'll still need to further synchronize the output
// of this stage.
//
// %%SYNTH:
//   set_false_path -from $nonscan_clks -to $inst/d_s1_reg/preset
//   set_false_path -from $nonscan_clks -through $inst/d_s1_reg/preset
//   set_false_path -from $scan_clks -through $inst/d_s1_reg/preset -to $nonscan_clks
//   set_false_path -from $nonscan_clks -to $inst/d_s2_reg/preset
//   set_false_path -from $nonscan_clks -through $inst/d_s2_reg/preset
//   set_false_path -from $scan_clks -through $inst/d_s2_reg/preset -to $nonscan_clks
//
reg d_s1, d_s2;
always @(posedge clk or posedge async_scan_rst) begin
  if (async_scan_rst) begin
    d_s1 <= 1'b1;
    d_s2 <= 1'b1;
  end 
  else begin
`ifdef ANI_SIM_MODE  // ifdef simulation mode only (not synth)
    if (MAX_CHK_EN) begin
      // Cause a timing violation on the d_s1 flop if the
      // preset input does not meet the SETUP requirement.
      // d_s1 is either randomized or set to QVAL based on RAND
      if (async_scan_rst_in_dly != async_scan_rst) begin
        if (QRND == 1)
          d_s1 <= `ANI_RANDOM;
        else
          d_s1 <= QVAL;
      end
      else begin
        d_s1 <= 1'b0;
      end
    end // (MAX_CHK_EN)
    else begin // Pessimistic metastability modelling.
      if ((META_FALL==1) & async_scan_rst==0) begin
        if (async_scan_rst != shadow) begin // if input changed since the last time we had a clock
          d_s1 <= `ANI_RANDOM;              // randomize the first flop
        end
        else begin
          d_s1 <= 1'b0;
        end
      end
      else begin
        d_s1 <= 1'b0;
      end
    end // Pessimistic metastability modelling.
`else
    d_s1 <= 1'b0;  // Synthesis path
`endif
    d_s2 <= d_s1 & ~atpg_sync_rst;
  end
end

// Synchronize the captured pulse since the rising edge
// of the pulse is still asynchronous.
//
wire d_sync_s1;
dwc_e12mp_phy_x4_ns_gen_sync #(.META_FALL(0)) sync (
  .q   (d_sync_s1),
  .rst (rst),
  .clk (clk),
  .d   (d_s2 & ~atpg_sync_rst)
);

generate
  if (NO_EDGE==1) begin : no_edge
    assign q = d_sync_s1;
  end 
  else begin : has_edge
    // Final edge detect output
    //
    reg d_sync_s2;
    always @(posedge clk or posedge rst) begin
      if (rst)
        d_sync_s2 <= 1'b0;
      else
        d_sync_s2 <= d_sync_s1;
    end

    if (FALLING_EDGE==0) begin : falling_edge
      assign q = !d_sync_s2 && d_sync_s1; // Rising edge detect
    end 
    else begin : rising_edge
      assign q = d_sync_s2 && !d_sync_s1; // Falling edge detect
    end
  end
endgenerate

// Test cover point for async_rst
reg atpg_cov;
always @(posedge clk or posedge scan_set_rst_i) begin
  if (scan_set_rst_i)
    atpg_cov <= 1'b0;
  else
    atpg_cov <= d;
end

endmodule
